#include "common.h"
#include "myFTL.h"

template <typename PageType>
class MyFTL : public FTLBase<PageType> {
public:

    /*
     * Constructor
     */
    MyFTL(const ConfBase *conf) {
    	/* Number of packages in a ssd */
	size_t ssd_size = conf->GetSSDSize();
	/* Number of dies in a package */
	size_t package_size = conf->GetPackageSize();
	/* Number of planes in a die */
	size_t die_size = conf->GetDieSize();
	/* Number of blocks in a plane */
	size_t plane_size = conf->GetPlaneSize();
	/* Number of pages in a block */
	size_t block_size = conf->GetBlockSize();
	/* Maximum number a block can be erased */
	size_t block_erase_count = conf->GetBlockEraseCount();
    	/* Overprovioned blocks as a percentage of total number of blocks */
	size_t op = conf->GetOverprovisioning();

	printf("SSD Configuration: %zu, %zu, %zu, %zu, %zu\n",
		ssd_size, package_size, die_size, plane_size, block_size);
	printf("Max Erase Count: %zu, Overprovisioning: %zu%%\n",
		block_erase_count, op);
    }

    /*
     * Destructor - Plase keep it as virtual to allow destroying the
     *              object with base type pointer
     */
    virtual ~MyFTL() {
    }

    /*
     * ReadTranslate() - Translates read address
     *
     * This function translates a physical LBA into an Address object that will
     * be used as the target address of the read operation.
     *
     * If you need to issue extra operations, please use argument func to
     * interact with class Controller
     */
    std::pair<ExecState, Address>
    ReadTranslate(size_t lba, const ExecCallBack<PageType> &func) {
        (void) lba;
        (void) func;
        return std::make_pair(ExecState::SUCCESS, Address(0, 0, 0, 0, 0));
    }

    /*
     * WriteTranslate() - Translates write address
     *
     * Please refer to ReadTranslate()
     */
    std::pair<ExecState, Address>
    WriteTranslate(size_t lba, const ExecCallBack<PageType> &func) {
        (void) lba;
        (void) func;
        return std::make_pair(ExecState::SUCCESS, Address(0, 0, 0, 0, 0));
    }

    /*
     * Optionally mark a LBA as a garbage.
     */
    ExecState
    Trim(size_t lba, const ExecCallBack<PageType>& func) {
        (void) lba;
        (void) func;
        return ExecState::SUCCESS;
    }
};

/*
 * CreateMyFTL() - Creates class MyFTL object
 *
 * You do not need to modify this
 */
FTLBase<TEST_PAGE_TYPE>* CreateMyFTL(const ConfBase *conf) {

	MyFTL<TEST_PAGE_TYPE> *ftl = new MyFTL<TEST_PAGE_TYPE>(conf);
	return static_cast<FTLBase<TEST_PAGE_TYPE>*>(ftl);
}
